import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:shared_preferences/shared_preferences.dart';

class DraggableFloatingButton extends StatefulWidget {
  final Widget child;
  final Offset initialOffset;
  final EdgeInsets margin;
  final PreferredEdge preferredEdge;
  final VoidCallback? onPressed;
  final bool enableHapticFeedback;
  final bool enableEdgeElasticity;
  final bool savePosition;
  final String positionStorageKey;
  final Duration animationDuration;
  final Curve animationCurve;

  const DraggableFloatingButton({
    Key? key,
    required this.child,
    this.initialOffset = Offset.zero,
    this.margin = EdgeInsets.zero,
    this.preferredEdge = PreferredEdge.right,
    this.onPressed,
    this.enableHapticFeedback = true,
    this.enableEdgeElasticity = true,
    this.savePosition = true,
    this.positionStorageKey = 'draggable_button_position',
    this.animationDuration = const Duration(milliseconds: 300),
    this.animationCurve = Curves.easeOutQuint,
  }) : super(key: key);

  @override
  _DraggableFloatingButtonState createState() =>
      _DraggableFloatingButtonState();
}

enum PreferredEdge { left, right, top, bottom }

class _DraggableFloatingButtonState extends State<DraggableFloatingButton> {
  late Offset _offset;
  late Offset _minOffset;
  late Offset _maxOffset;
  bool _isDragging = false;
  Size? _screenSize;
  Size? _childSize;
  bool _initialized = false;
  final GlobalKey _childKey = GlobalKey();

  @override
  void initState() {
    super.initState();
    _offset = widget.initialOffset;
    _loadSavedPosition();
  }

  Future<void> _loadSavedPosition() async {
    if (!widget.savePosition) return;

    try {
      final prefs = await SharedPreferences.getInstance();
      final savedX = prefs.getDouble('${widget.positionStorageKey}_x');
      final savedY = prefs.getDouble('${widget.positionStorageKey}_y');

      if (savedX != null && savedY != null) {
        setState(() {
          _offset = Offset(savedX, savedY);
        });
      }
    } catch (e) {
      debugPrint('Failed to load saved position: $e');
    }
  }

  Future<void> _savePosition() async {
    if (!widget.savePosition) return;

    try {
      final prefs = await SharedPreferences.getInstance();
      await prefs.setDouble('${widget.positionStorageKey}_x', _offset.dx);
      await prefs.setDouble('${widget.positionStorageKey}_y', _offset.dy);
    } catch (e) {
      debugPrint('Failed to save position: $e');
    }
  }

  void _updateScreenSize() {
    _screenSize = MediaQuery.of(context).size;

    // 确保child尺寸已经测量
    if (_childSize == null) {
      final renderBox =
          _childKey.currentContext?.findRenderObject() as RenderBox?;
      if (renderBox != null) {
        _childSize = renderBox.size;
      }
    }

    if (_childSize == null || _screenSize == null) return;

    _minOffset = Offset(
      widget.margin.left,
      widget.margin.top,
    );
    _maxOffset = Offset(
      _screenSize!.width - _childSize!.width - widget.margin.right,
      _screenSize!.height - _childSize!.height - widget.margin.bottom,
    );

    // 确保初始位置在有效范围内
    _offset = Offset(
      _offset.dx.clamp(_minOffset.dx, _maxOffset.dx),
      _offset.dy.clamp(_minOffset.dy, _maxOffset.dy),
    );

    if (!_initialized) {
      _initialized = true;
      WidgetsBinding.instance.addPostFrameCallback((_) {
        _snapToEdge(animate: false);
      });
    }
  }

  void _vibrate() {
    if (widget.enableHapticFeedback) {
      HapticFeedback.lightImpact();
    }
  }

  void _snapToEdge({bool animate = true}) {
    if (_screenSize == null || _childSize == null) return;

    final buttonCenter =
        _offset + Offset(_childSize!.width / 2, _childSize!.height / 2);

    Offset targetOffset;

    switch (widget.preferredEdge) {
      case PreferredEdge.left:
        targetOffset =
            Offset(_minOffset.dx, buttonCenter.dy - _childSize!.height / 2);
        break;
      case PreferredEdge.right:
        targetOffset =
            Offset(_maxOffset.dx, buttonCenter.dy - _childSize!.height / 2);
        break;
      case PreferredEdge.top:
        targetOffset =
            Offset(buttonCenter.dx - _childSize!.width / 2, _minOffset.dy);
        break;
      case PreferredEdge.bottom:
        targetOffset =
            Offset(buttonCenter.dx - _childSize!.width / 2, _maxOffset.dy);
        break;
    }

    // 确保位置在有效范围内
    targetOffset = Offset(
      targetOffset.dx.clamp(_minOffset.dx, _maxOffset.dx),
      targetOffset.dy.clamp(_minOffset.dy, _maxOffset.dy),
    );

    if (animate) {
      _vibrate();
    }

    if (targetOffset != _offset) {
      setState(() {
        _offset = targetOffset;
      });
      _savePosition();
    }
  }

  Offset _applyEdgeElasticity(Offset offset) {
    if (!widget.enableEdgeElasticity || _childSize == null) return offset;

    const elasticityFactor = 0.3;
    final overshootX = (offset.dx < _minOffset.dx)
        ? (_minOffset.dx - offset.dx) * elasticityFactor
        : (offset.dx > _maxOffset.dx)
            ? (_maxOffset.dx - offset.dx) * elasticityFactor
            : 0;

    final overshootY = (offset.dy < _minOffset.dy)
        ? (_minOffset.dy - offset.dy) * elasticityFactor
        : (offset.dy > _maxOffset.dy)
            ? (_maxOffset.dy - offset.dy) * elasticityFactor
            : 0;

    return Offset(offset.dx + overshootX, offset.dy + overshootY);
  }

  @override
  Widget build(BuildContext context) {
    return LayoutBuilder(
      builder: (context, constraints) {
        WidgetsBinding.instance
            .addPostFrameCallback((_) => _updateScreenSize());

        return SizedBox(
          width: _screenSize?.width,
          height: _screenSize?.height,
          child: Stack(
            clipBehavior: Clip.none, // 确保child不会被裁剪
            children: [
              AnimatedPositioned(
                duration:
                    _isDragging ? Duration.zero : widget.animationDuration,
                curve: _isDragging ? Curves.linear : widget.animationCurve,
                left: _offset.dx,
                top: _offset.dy,
                child: GestureDetector(
                  onPanStart: (details) {
                    setState(() {
                      _isDragging = true;
                    });
                  },
                  onPanUpdate: (details) {
                    setState(() {
                      _offset = _applyEdgeElasticity(_offset + details.delta);
                    });
                  },
                  onPanEnd: (details) {
                    setState(() {
                      _isDragging = false;
                      // 限制在屏幕范围内
                      _offset = Offset(
                        _offset.dx.clamp(_minOffset.dx, _maxOffset.dx),
                        _offset.dy.clamp(_minOffset.dy, _maxOffset.dy),
                      );
                    });
                    _snapToEdge();
                  },
                  onTap: widget.onPressed,
                  child: Container(
                    key: _childKey,
                    child: AnimatedContainer(
                      duration: const Duration(milliseconds: 200),
                      transform: Matrix4.identity()
                        ..scale(_isDragging ? 1.1 : 1.0),
                      child: AnimatedOpacity(
                        opacity: _isDragging ? 0.8 : 1.0,
                        duration: const Duration(milliseconds: 200),
                        child: Material(
                          elevation: _isDragging ? 12.0 : 6.0,
                          borderRadius: BorderRadius.circular(30),
                          color: Colors.transparent,
                          child: widget.child,
                        ),
                      ),
                    ),
                  ),
                ),
              ),
            ],
          ),
        );
      },
    );
  }
}
